package com.lzy.util;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lzy.constant.BaseImgEnum;
import com.lzy.model.RestResponseResult;
import jodd.net.URLDecoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * HTTP请求工具
 *
 * @author donaldhan
 */
@Slf4j
public final class HttpUtil {
    private final static String URL = "https://cd.hxxfvip.com/ossfile/downloadPicture";

    /**
     * Http get请求
     *
     * @param url              请求地址
     * @param header           头部信息
     * @param parameterDataMap 请求的参数
     * @param socketTimeout
     * @param connectTimeout
     */
    public static String apiGetRequest(String url, Map<String, String> header, Map<String, String> parameterDataMap, int socketTimeout, int connectTimeout) throws IOException {
        if (!CollectionUtils.isEmpty(parameterDataMap)) {
            try {
                URIBuilder uriBuilder = new URIBuilder(url);
                if (!CollectionUtils.isEmpty(parameterDataMap)) {
                    parameterDataMap.entrySet().forEach(e -> {
                        uriBuilder.addParameter(e.getKey(), e.getValue());
                    });
                }
                url = uriBuilder.build().toString();
            } catch (URISyntaxException e) {
                log.error("url错误");
                throw new RuntimeException("url错误");
            }
        }
        log.info("请求的URL：{}", url);

        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpGet.setConfig(requestConfig);

        return httpExecute(httpGet, header);
    }

    /**
     * get 请求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static String apiGetRequest(String url) throws IOException {
        return apiGetRequest(url, null, null, 5000, 5000);
    }

    /**
     * Http post form请求
     *
     * @param url              请求地址
     * @param header           头部信息
     * @param parameterDataMap 请求的参数
     * @param socketTimeout
     * @param connectTimeout
     */
    public static String apiPostRequestForm(String url, Map<String, String> header, Map<String, String> parameterDataMap, int socketTimeout, int connectTimeout) throws IOException {
        log.info("请求的URL为：{}", url);
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpPost.setConfig(requestConfig);

        if (!CollectionUtils.isEmpty(parameterDataMap)) {
            List<NameValuePair> formParams = new ArrayList<>();
            parameterDataMap.entrySet().forEach(e -> {
                formParams.add(new BasicNameValuePair(e.getKey(), e.getValue()));
            });
            HttpEntity entity = new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8);
            httpPost.setEntity(entity);
            log.info("请求的参数为：{}", URLDecoder.decode(EntityUtils.toString(entity)));
        }

        return httpExecute(httpPost, header);
    }

    /**
     * Http post form请求
     *
     * @param url            请求地址
     * @param header         头部信息
     * @param bodyStr        body内容
     * @param contentType    内容类型
     * @param socketTimeout
     * @param connectTimeout
     */
    public static String apiPostRequestBody(String url, Map<String, String> header, String bodyStr, String contentType, int socketTimeout, int connectTimeout) throws IOException {
        log.info("请求的URL为：{}", url);
        log.info("请求的body内容为：{}", bodyStr);
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpPost.setConfig(requestConfig);
        StringEntity entity = new StringEntity(bodyStr, "UTF-8");
        entity.setContentType(contentType);
        httpPost.setEntity(entity);

        return httpExecute(httpPost, header);
    }

    private static String httpExecute(HttpUriRequest request, Map<String, String> headerMap) throws IOException {
        log.info("请求方式为：{}", request.getMethod());
        if (!CollectionUtils.isEmpty(headerMap)) {
            headerMap.forEach(request::setHeader);
        }

        for (Header header : request.getAllHeaders()) {
            log.info("请求的header为：{}", header);
        }

        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(request);
        for (Header header1 : response.getAllHeaders()) {
            log.info("返回的header为：{}", header1);
        }
        log.info("返回的状态码为：{}", response.getStatusLine());
        String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
        log.info("返回的数据为：{}", result);
        response.close();
        httpClient.close();

        return result;
    }

    /**
     * 获取Body内容
     *
     * @param request
     * @return bodyStr
     */
    public static String getRequestBodyContent(HttpServletRequest request) throws IOException {
        BufferedReader bufferedReader = request.getReader();
        StringBuilder dataStrBuf = new StringBuilder();
        String dataTemp;

        while ((dataTemp = bufferedReader.readLine()) != null) {
            dataStrBuf.append(dataTemp);
        }
        bufferedReader.close();

        String content = dataStrBuf.toString();
        if (!StringUtils.isEmpty(content)) {
            log.info("请求的body内容为:{}", content);
            return dataStrBuf.toString();
        } else {
            log.info("请求的body内容为空!");
            return null;
        }
    }

    /**
     * Post下载图片
     *
     * @param url              url
     * @param headerMap        请求头部标识
     * @param parameterDataMap 请求参数
     * @param socketTimeout    socket超时
     * @param connectTimeout   connect超时
     * @return
     * @throws IOException
     */
    public static ByteArrayOutputStream postDownloadFile(String url, Map<String, String> headerMap, Map<String, String> parameterDataMap, int socketTimeout, int connectTimeout) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpPost.setConfig(requestConfig);
        if (!CollectionUtils.isEmpty(headerMap)) {
            headerMap.forEach(httpPost::setHeader);
        }
        for (Header header : httpPost.getAllHeaders()) {
            log.info("请求的header为：{}", header);
        }
        if (!CollectionUtils.isEmpty(parameterDataMap)) {
            List<NameValuePair> formParams = new ArrayList<>();
            parameterDataMap.forEach((key, value) -> formParams.add(new BasicNameValuePair(key, value)));
            HttpEntity entity = new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8);
            httpPost.setEntity(entity);
            log.info("请求的参数为：{}", URLDecoder.decode(EntityUtils.toString(entity)));
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpPost);
        InputStream inputStream = response.getEntity().getContent();
        ByteArrayOutputStream outputStream = cloneInputStream(inputStream);
        httpClient.close();
        return outputStream;
    }

    /**
     * http下载文件
     *
     * @param url 请求url
     * @param headerMap 请求头部
     * @param socketTimeout    socket超时
     * @param connectTimeout   connect超时
     * @return InputStream
     */
    public static byte[] downloadFile(String url, Map<String, String> headerMap, int socketTimeout, int connectTimeout) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpGet.setConfig(requestConfig);

        if (!CollectionUtils.isEmpty(headerMap)) {
            headerMap.forEach(httpGet::setHeader);
        }
        for (Header header : httpGet.getAllHeaders()) {
            log.info("请求的header为：{}", header);
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        InputStream inputStream = response.getEntity().getContent();
        ByteArrayOutputStream outputStream = cloneInputStream(inputStream);
        byte[] bytes = outputStream.toByteArray();
        httpClient.close();
        return bytes;
    }

    /**
     * json方式下载
     *
     * @param url              url
     * @param parameterDataMap 请求参数
     * @param socketTimeout    socket超时
     * @param connectTimeout   connect超时
     * @return
     * @throws IOException
     */
    public static ByteArrayOutputStream jsonPostDownloadFile(String url, Map<String, String> parameterDataMap, int socketTimeout, int connectTimeout) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpPost.setConfig(requestConfig);
        httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
        if (!CollectionUtils.isEmpty(parameterDataMap)) {
            StringEntity entity = new StringEntity(JsonUtils.objectToJson(parameterDataMap));
            entity.setContentType("image/png");
            httpPost.setEntity(entity);
            log.info("请求的参数为：{}", URLDecoder.decode(EntityUtils.toString(entity)));
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpPost);
        InputStream inputStream = response.getEntity().getContent();
        ByteArrayOutputStream outputStream = cloneInputStream(inputStream);
        httpClient.close();
        return outputStream;
    }

    /**
     * 下载图片，返回Base64
     *
     * @param priUlr
     * @return
     */
    public static String downloadPictureToBase64(String priUlr, String type) {
        URL url;
        try {
            byte[] data;
            url = new URL(priUlr);
            DataInputStream dataInputStream = new DataInputStream(url.openStream());
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = dataInputStream.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            data = swapStream.toByteArray();
            String encoder = Base64Util.encoder(data);
            BaseImgEnum baseImgEnum = BaseImgEnum.valueOfCode(type);
            return baseImgEnum.getValue() + encoder;
        } catch (IOException e) {
            log.error("下载图片失败:", e);
            return "";
        }
    }


    //上传图片
    public static String uploadPicture(String priUlr, String type) throws IOException {
        HashMap<String, String> headMap = new HashMap<>();
        HashMap<String, String> bodyMap = new HashMap<>();
        bodyMap.put("imageBase64Str", downloadPictureToBase64(priUlr, type));
        return apiPostRequestBody(URL, headMap, JsonUtils.objectToJson(bodyMap), "application/json", 5000, 5000);
    }

    public static String uploadPictureByUrl(String priUir, String type) {
        HashMap<String, String> bodyMap = new HashMap<>();
        bodyMap.put("priUlr", priUir);
        bodyMap.put("type", type);
        try {
            String requestBody = apiPostRequestBody(URL, new HashMap<>(), JsonUtils.objectToJson(bodyMap), "application/json", 5000, 5000);
            if (StringUtils.isEmpty(requestBody)) {
                return "";
            }
            RestResponseResult<String> response = new Gson().fromJson(requestBody, new TypeToken<RestResponseResult<String>>() {
            }.getType());
            if (response.isSuccess()) {
                return response.getData();
            }
            log.error("获取图片异常:{}", response.getMessage());
            return "";
        } catch (IOException e) {
            log.error("获取图片异常:", e);
            return "";
        }

    }


    private static ByteArrayOutputStream cloneInputStream(InputStream input) throws IOException {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
        } catch (IOException e) {
            log.error("读取下载内容失败", e);
            throw e;
        }
    }


}